package com.wuge.service.impl;

import com.alibaba.fastjson.JSON;
import com.wuge.common.to.es.SkuEsModel;
import com.wuge.service.ProductSaveService;
import com.wuge.service.ProductSeachService;
import com.wuge.vo.SearchParm;
import com.wuge.vo.SearchResult;
import org.apache.http.HttpRequest;
import org.apache.lucene.search.TotalHits;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedGeoBounds;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.thymeleaf.util.NumberUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

import static org.elasticsearch.action.admin.indices.stats.CommonStatsFlags.Flag.Search;

@Service
public class ProductSeachServiceImpl implements ProductSeachService {
    @Resource
    RestHighLevelClient restHighLevelClient;

    @Override
    public SearchResult searchByParm(SearchParm searchParm, HttpServletRequest httpRequest) throws IOException {
        String queryString = httpRequest.getQueryString();
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("mall_product");
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        String keyword = searchParm.getKeyword();
        if (!StringUtils.isEmpty(keyword)) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("skuTitle", keyword));
        }

        Long catalog3Id = searchParm.getCatalog3Id();
        if (catalog3Id != null && catalog3Id != 0) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("catalogId", catalog3Id));
        }
        List<Long> brandId = searchParm.getBrandId();
        if (!CollectionUtils.isEmpty(brandId)) {
            boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId", brandId));
        }
        Integer hasStock = searchParm.getHasStock();
        if (hasStock!=null){
        boolQueryBuilder.filter(QueryBuilders.termQuery("hasStock", hasStock == 1));}
        String skuPrice = searchParm.getSkuPrice();
        if (!StringUtils.isEmpty(skuPrice)) {
            String[] str = skuPrice.split("_");
//            split可以分割出空字符串
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("skuPrice");
            if (str.length == 2) {
                rangeQuery.gte(str[0]);
                rangeQuery.lte(str[1]);
//            } else if (str.length == 1) {
//                if (skuPrice.startsWith("_")) {
//                    rangeQuery.lte(str[0]);
//                } else {
//                    rangeQuery.gte(str[0]);
//                }
            }
            boolQueryBuilder.filter(rangeQuery);
        }
        List<String> attrs = searchParm.getAttrs();
        if (!CollectionUtils.isEmpty(attrs)) {
//TODO XIAC

            for (String attr : attrs) {
                BoolQueryBuilder boolQueryBuilder1 = QueryBuilders.boolQuery();
                NestedQueryBuilder nested = QueryBuilders.nestedQuery("attrs", boolQueryBuilder1, ScoreMode.None);
                String[] s = attr.split("_");
                String attrId = s[0];
                String[] values = s[1].split(":");
                boolQueryBuilder1.must(QueryBuilders.termQuery("attrs.attrId", attrId));
                boolQueryBuilder1.must(QueryBuilders.termsQuery("attrs.attrValue", values));

                boolQueryBuilder.filter(nested);
            }

        }
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQueryBuilder);
        String sort = searchParm.getSort();
//        排序
        if (!StringUtils.isEmpty(sort)) {
            String[] split = sort.split("_");

            if (split[1].equalsIgnoreCase("asc")) {
                sourceBuilder.sort(split[0], SortOrder.ASC);
            } else {
                sourceBuilder.sort(split[0], SortOrder.DESC);
            }
        }
//        分页
        Integer pageNum = searchParm.getPageNum();
        int l = (pageNum - 1) * 2;
        sourceBuilder.from(l);
        sourceBuilder.size(2);
        if (!StringUtils.isEmpty(searchParm.getKeyword())) {
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.preTags("<b style='color:red'>");
            highlightBuilder.postTags("</b>");
            highlightBuilder.field("skuTitle");
            sourceBuilder.highlighter(highlightBuilder);
        }
//聚合查询
        TermsAggregationBuilder brandAgg = AggregationBuilders.terms("brandAgg");
        brandAgg.field("brandId").size(10);
        TermsAggregationBuilder brandNameAgg = AggregationBuilders.terms("brandNameAgg");
        brandNameAgg.field("brandName").size(10);
        TermsAggregationBuilder brandImg = AggregationBuilders.terms("brandImgAgg");
        brandImg.field("brandImg").size(10);
        brandAgg.subAggregation(brandNameAgg).subAggregation(brandImg);
        sourceBuilder.aggregation(brandAgg);
        TermsAggregationBuilder catalogAgg = AggregationBuilders.terms("catalogAgg").field("catalogId").size(10);
        catalogAgg.subAggregation(AggregationBuilders.terms("catalogNameAgg").field("catalogName").size(10));
        sourceBuilder.aggregation(catalogAgg);
        NestedAggregationBuilder nested = AggregationBuilders.nested("attrs", "attrs");
        TermsAggregationBuilder attrIdAgg = AggregationBuilders.terms("attrIdAgg").field("attrs.attrId").size(10);
        nested.subAggregation(attrIdAgg) ;

        attrIdAgg.subAggregation(AggregationBuilders.terms("attrNameAgg").field("attrs.attrName").size(10));
        attrIdAgg.subAggregation(AggregationBuilders.terms("attrValueAgg").field("attrs.attrValue").size(10));
        sourceBuilder.aggregation(nested);
        System.out.println("DSL语句为" + sourceBuilder.toString());
        searchRequest.source(sourceBuilder);
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchResult searchResult=getSearchResult(search,searchParm,queryString);

        return searchResult;
    }

    private SearchResult getSearchResult(SearchResponse search, SearchParm searchParm, String queryString) {
        SearchResult searchResult = new SearchResult();
        //获取到的sku集合
        SearchHits hits = search.getHits();
        List<SkuEsModel> list = new ArrayList<>();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            SkuEsModel skuEsModel = JSON.parseObject(sourceAsString, SkuEsModel.class);
            if (!StringUtils.isEmpty(searchParm.getKeyword())) {
                String skuTitle = hit.getHighlightFields().get("skuTitle").getFragments()[0].toString();
                skuEsModel.setSkuTitle(skuTitle);
            }
            list.add(skuEsModel);
        }
        searchResult.setProduct(list);
        //当前页码
        searchResult.setPageNum(searchParm.getPageNum());
        //总记录
        long value = search.getHits().getTotalHits().value;
        searchResult.setTotal(value);
        //总页码
        int totalPage = (int) (value % 2 == 0 ? value / 2 : value / 2 + 1);

        Integer[] sequence = NumberUtils.sequence(1, totalPage);
        List<Integer> integerList = Arrays.asList(sequence);
        searchResult.setPageNavs(integerList);

        searchResult.setTotalPages(totalPage);
        //所有的品牌
        ParsedLongTerms brandAgg = search.getAggregations().get("brandAgg");
        List<SearchResult.BrandVo> brandVos = brandAgg.getBuckets().stream().map(
                buck -> {
                    SearchResult.BrandVo brandVo = new SearchResult.BrandVo();
                    brandVo.setBrandId(((Terms.Bucket) buck).getKeyAsNumber().longValue());
                    ParsedStringTerms brandName = ((Terms.Bucket) buck).getAggregations().get("brandNameAgg");
                    String name = brandName.getBuckets().get(0).getKeyAsString();
                    brandVo.setBrandName(name);
                    ParsedStringTerms brandImg = ((Terms.Bucket) buck).getAggregations().get("brandImgAgg");
                    String Img = brandImg.getBuckets().get(0).getKeyAsString();
                    brandVo.setBrandImg(Img);
                    return brandVo;
                }
        ).collect(Collectors.toList());
        searchResult.setBrands(brandVos);


        //所有分类
        ParsedLongTerms catalogAgg = search.getAggregations().get("catalogAgg");
        List<SearchResult.CatalogVo> catalogVos = catalogAgg.getBuckets().stream().map((catalog) -> {
            SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo();
            catalogVo.setCatalogId(((Terms.Bucket) catalog).getKeyAsNumber().longValue());
            String catalogName = ((ParsedStringTerms) (((Terms.Bucket) catalog).getAggregations().get("catalogNameAgg"))).getBuckets().get(0).getKeyAsString();
            catalogVo.setCatalogName(catalogName);
            return catalogVo;
        }).collect(Collectors.toList());
        searchResult.setCatalogs(catalogVos);
        //所有的属性
        ParsedNested attrs = search.getAggregations().get("attrs");
        ParsedLongTerms parsedLongTerms = attrs.getAggregations().get("attrIdAgg");
        List<SearchResult.AttrVo> attrVos = parsedLongTerms.getBuckets().stream().map((att) -> {
            SearchResult.AttrVo attrVo = new SearchResult.AttrVo();
            attrVo.setAttrId(((Terms.Bucket) att).getKeyAsNumber().longValue());
            attrVo.setAttrName((((ParsedStringTerms) ((Terms.Bucket) att).getAggregations().get("attrNameAgg"))).getBuckets().get(0).getKeyAsString());
            ParsedStringTerms attrValueAgg = ((Terms.Bucket) att).getAggregations().get("attrValueAgg");
            List<String> values = attrValueAgg.getBuckets().stream().map((attrValue) -> {
                String keyAsString = ((Terms.Bucket) attrValue).getKeyAsString();
                return keyAsString;

            }).collect(Collectors.toList());
            attrVo.setAttrValue(values);
            return attrVo;
        }).collect(Collectors.toList());

        searchResult.setAttrs(attrVos);
        System.out.println(searchResult);
        List<String> parmAttrs = searchParm.getAttrs();
        Map<Long, String> map = searchResult.getAttrs().stream().collect(Collectors.toMap(attr -> {
            return attr.getAttrId();
        }, attr -> {
            return attr.getAttrName();
        }));
//        不想循环查表又想获取名称????
        if (!CollectionUtils.isEmpty(searchParm.getAttrs())){
        List<SearchResult.NavVo> navVos = searchParm.getAttrs().stream().map((attr) -> {
            SearchResult.NavVo navVo = new SearchResult.NavVo();
            String[] s = attr.split("_");
            long id = Long.parseLong(s[0]);
            navVo.setNavName(s[1]);
            navVo.setNavName(map.get(id));
            String ss = null;
            try {
                ss = URLEncoder.encode(attr, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            String R = queryString.replace("&attrs="+ss, "");
             R = R.replace("attrs="+attr, "");
            navVo.setLink("http://search.gulimall.com/list.html?" + R);
            return navVo;
        }).collect(Collectors.toList());
            searchResult.setNavs(navVos);
        }

        return searchResult;
    }
}
